home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The X-Philes (2nd Revision)
/
The X-Philes Number 1 (1995).iso
/
xphiles
/
hp95
/
gnuchess.arc
/
piece.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-01-16
|
32KB
|
1,543 lines
/**********************************************************************/
/* Following code copied from nuxdsp.c and modified a lot for */
/* the small 16x40 screen of the HP95. Also added lots of screen */
/* optimisations because the HP95 is slow at screen access and */
/* for short thinking times, the time is dominated by the screen */
/* update. */
/* */
/* Written by Paul Fox and hereby placed under terms of the GNU */
/* general license. (January 1992) */
/**********************************************************************/
#include <ctype.h>
#include <signal.h>
# if defined(MSDOS)
# include <dos.h>
# include <conio.h>
# else
# define cdecl
# define huge
# define far
# define kbhit() 1
# define getch() getchar()
# endif
#include "hp95.h"
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "gnuchess.h"
#define ESC 0x1B
#define refresh() fflush(stdout)
/**********************************************************************/
/* Line numbers (starting from zero) where certain messages go. */
/**********************************************************************/
# define LINE_TOP_PIECES 1
# define LINE_DEPTH 2
# define LINE_MAX_TREE 8
# define LINE_YOUR_GO 13
# define LINE_BOT_PIECES 14
# define MAX_LINES 16
int ttcol;
int ttrow;
int ttwidth[MAX_LINES];
struct bitmap {
G_AREA info;
char bits[30];
};
struct bitmap bitmap[] = {
# include "pieces.bm"
};
struct bitmap *w_on_b_piece[] = {
&bitmap[0],
&bitmap[1], &bitmap[2], &bitmap[3], &bitmap[4], &bitmap[5], &bitmap[6]
};
struct bitmap *w_on_w_piece[] = {
&bitmap[7],
&bitmap[8], &bitmap[9], &bitmap[10], &bitmap[11], &bitmap[12], &bitmap[13]
};
struct bitmap *b_on_w_piece[] = {
&bitmap[14],
&bitmap[15], &bitmap[16], &bitmap[17], &bitmap[18], &bitmap[19], &bitmap[20]
};
struct bitmap *b_on_b_piece[] = {
&bitmap[21],
&bitmap[22], &bitmap[23], &bitmap[24], &bitmap[25], &bitmap[26], &bitmap[27]
};
# define TAB 21
char pxx[] = " PNBRQK";
char qxx[] = " pnbrqk";
char rxx[] = "12345678";
char cxx[] = "abcdefgh";
#define VIR_C(s) ((flag.reverse) ? 7-column(s) : column(s))
#define VIR_R(s) ((flag.reverse) ? 7-row(s) : row(s))
#define Vblack(s) (!((VIR_C(s) + VIR_R(s)) % 2))
static char mvstr[4][6];
static char* ColorStr[2] = {"White", "Black"};
static long evrate;
short PositionFlag = 0;
short coords = 1;
static void param (short n);
void TerminateSearch (int), Die (int);
void draw_bitmap();
void draw_piece(int, int, struct bitmap *);
long read_number(long);
void read_line(char *);
void
Initialize(void)
{
ClrScreen();
gotoXY(0, 0);
G_Mode(G_GRAPHICS);
gotoXY(5, 5);
printz("GNU CHESS 3.1 FOR THE HP95");
gotoXY(5, 7);
printz(" RELEASE 1.02 BY PAUL FOX");
refresh();
signal(SIGINT, Die);
}
void
ExitChess (void)
{
ListGame ();
G_Mode(G_ALPHA);
gotoXY(0, 15);
printf("\n\n");
exit (0);
}
char *
count_pieces(short side)
{ register int i;
static char buf[20];
char *cp;
cp = buf;
if (side == white)
i = 1;
else
i = 2;
for ( ; i <= GameCnt; i += 2) {
if (GameList[i].piece)
*cp++ = pxx[GameList[i].piece];
}
*cp = '\0';
return buf;
}
void
read_line(str)
char *str;
{ char *cp = str;
int ch;
int counter;
char cursor_type = '_';
while (1) {
*cp = '\0';
counter = 0;
write(1, &cursor_type, 1);
while (1) {
if (kbhit())
break;
if (counter == 0) {
write(1, "\b \b", 3);
write(1, &cursor_type, 1);
}
if (counter++ < 40)
continue;
counter = 0;
if (cursor_type == '_')
cursor_type = ' ';
else
cursor_type = '_';
}
write(1, "\b \b", 3);
ch = getch();
if (ch == 0) {
getch();
continue;
}
if (ch == '\b' || ch == 0x7f) {
if (cp > str) {
ttwidth[ttrow]--;
cp--;
write(1, "\b \b", 3);
}
continue;
}
if (ch == '\n' || ch == '\r')
return;
*cp = ch;
write(1, cp++, 1);
ttwidth[ttrow]++;
}
}
long
read_number(val)
long val;
{ char s[80];
read_line(s);
if (s[0] == '\0')
return val;
return atoi(s);
}
void
Die (int Sig)
{
char s[80];
signal (SIGINT, SIG_IGN);
Sig++; /* shut up the compiler */
ShowMessage ("Abort? ");
read_line(s);
if (strcmp (s, "yes") == 0)
ExitChess ();
signal (SIGINT, Die);
}
void
TerminateSearch (int Sig)
{
signal (SIGINT, SIG_IGN);
Sig++; /* shut up the compiler */
flag.timeout = true;
flag.bothsides = false;
signal (SIGINT, Die);
}
void
algbr (short int f, short int t, short int flag)
/*
Generate move strings in different formats.
*/
{
int m3p;
if (f != t)
{
/* algebraic notation */
mvstr[0][0] = cxx[column (f)];
mvstr[0][1] = rxx[row (f)];
mvstr[0][2] = cxx[column (t)];
mvstr[0][3] = rxx[row (t)];
mvstr[0][4] = mvstr[3][0] = '\0';
if ((mvstr[1][0] = pxx[board[f]]) == 'P')
{
if (mvstr[0][0] == mvstr[0][2]) /* pawn did not eat */
{
mvstr[2][0] = mvstr[1][0] = mvstr[0][2]; /* to column */
mvstr[2][1] = mvstr[1][1] = mvstr[0][3]; /* to row */
m3p = 2;
}
else
/* pawn ate */
{
mvstr[2][0] = mvstr[1][0] = mvstr[0][0]; /* from column */
mvstr[2][1] = mvstr[1][1] = mvstr[0][2]; /* to column */
mvstr[2][2] = mvstr[0][3];
m3p = 3; /* to row */
}
mvstr[2][m3p] = mvstr[1][2] = '\0';
if (flag & promote)
{
mvstr[0][4] = mvstr[1][2] = mvstr[2][m3p] = qxx[flag & pmask];
mvstr[1][3] = mvstr[2][m3p + 1] = mvstr[0][5] = '\0';
}
}
else
/* not a pawn */
{
mvstr[2][0] = mvstr[1][0];
mvstr[2][1] = mvstr[0][1];
mvstr[2][2] = mvstr[1][1] = mvstr[0][2]; /* to column */
mvstr[2][3] = mvstr[1][2] = mvstr[0][3]; /* to row */
mvstr[2][4] = mvstr[1][3] = '\0';
strcpy (mvstr[3], mvstr[2]);
mvstr[3][1] = mvstr[0][0];
if (flag & cstlmask)
{
if (t > f)
{
strcpy (mvstr[1], "o-o");
strcpy (mvstr[2], "O-O");
}
else
{
strcpy (mvstr[1], "o-o-o");
strcpy (mvstr[2], "O-O-O");
}
}
}
}
else
mvstr[0][0] = mvstr[1][0] = mvstr[2][0] = mvstr[3][0] = '\0';
}
int
VerifyMove (char *s, short int iop, short unsigned int *mv)
/*
Compare the string 's' to the list of legal moves available for the
opponent. If a match is found, make the move on the board.
*/
{
static short pnt, tempb, tempc, tempsf, tempst, cnt;
static struct leaf xnode;
struct leaf *node;
*mv = 0;
if (iop == 2)
{
UnmakeMove (opponent, &xnode, &tempb, &tempc, &tempsf, &tempst);
return (false);
}
cnt = 0;
MoveList (opponent, 2);
pnt = TrPnt[2];
while (pnt < TrPnt[3])
{
node = &Tree[pnt++];
algbr (node->f, node->t, (short) node->flags);
if (strcmp (s, mvstr[0]) == 0 || strcmp (s, mvstr[1]) == 0 ||
strcmp (s, mvstr[2]) == 0 || strcmp (s, mvstr[3]) == 0)
{
cnt++;
xnode = *node;
}
}
if (cnt == 1)
{
MakeMove (opponent, &xnode, &tempb, &tempc, &tempsf, &tempst, &INCscore);
if (SqAtakd (PieceList[opponent][0], computer))
{
UnmakeMove (opponent, &xnode, &tempb, &tempc, &tempsf, &tempst);
ShowMessage ("Illegal Move!!");
return (false);
}
else
{
if (iop == 1)
return (true);
UpdateDisplay (xnode.f, xnode.t, 0, (short) xnode.flags);
if ((board[xnode.t] == pawn)
|| (xnode.flags & capture)
|| (xnode.flags & cstlmask))
{
Game50 = GameCnt;
ZeroRPT ();
}
GameList[GameCnt].depth = GameList[GameCnt].score = 0;
GameList[GameCnt].nodes = 0;
ElapsedTime (1);
GameList[GameCnt].time = (short) et;
TimeControl.clock[opponent] -= et;
--TimeControl.moves[opponent];
*mv = (xnode.f << 8) | xnode.t;
algbr (xnode.f, xnode.t, false);
return (true);
}
}
if (cnt > 1)
ShowMessage ("Ambiguous Move!");
return (false);
}
void
help (void)
{
ClrScreen ();
printz ("g1f3 or Nf3 move from g1->f3 or N->f3\n");
printz ("quit Exit Chess\n");
printz ("beep on/off\n");
printz ("o-o or o-o-o castle king/queen side\n");
printz ("easy on/off\n");
printz ("hash on/off\n");
printz ("bd redraw board\n");
printz ("reverse board display\n");
printz ("list game to chess.lst\n");
printz ("book on/off\n");
printz ("undo undo last ply\n");
printz ("remove take back a move\n");
printz ("edit edit board\n");
printz ("force enter game moves\n");
printz (" Hit <Enter> to continue...");
while (getchar() != '\n')
;
ClrScreen ();
printz ("switch sides with computer\n");
printz ("both computer match\n");
printz ("white computer plays white\n");
printz ("black computer plays black\n");
printz ("depth set search depth\n");
printz ("level select level\n");
printz ("post principle variation\n");
printz ("hint suggest a move\n");
printz ("save game to file\n");
printz ("get game from file\n");
printz ("random randomize play\n");
printz ("new start new game\n");
printz ("coords toggle coords\n");
printz ("p show coordinate values\n");
printz (" Hit <Enter> to continue...");
while (getchar() != '\n')
;
ClrScreen ();
printz ("Computer: %s\n", ColorStr[computer]);
printz ("Opponent: %s\n", ColorStr[opponent]);
printz ("Level: %ld\n", Level);
printz ("Easy mode: %s\n", (flag.easy) ? "ON" : "OFF");
printz ("Depth: %d\n", MaxSearchDepth);
printz ("Random: %s\n", (dither) ? "ON" : "OFF");
printz ("Transposition table: %s\n\n", (flag.hash) ? "ON" : "OFF");
printz (" Hit <Enter> to continue...");
while (getchar() != '\n')
;
ClrScreen ();
UpdateDisplay (0, 0, 1, 0);
}
void
EditBoard (void)
/*
Set up a board position. Pieces are entered by typing the piece
followed by the location. For example, Nf3 will place a knight on
square f3.
*/
{ register short sq;
short a, r, c, i;
char s[80];
ClrScreen ();
UpdateDisplay (0, 0, 1, 0);
gotoXY (TAB, 3);
printz (". Exit to main");
gotoXY (TAB, 4);
printz ("# Clear board");
gotoXY (TAB, 5);
printz ("c Change sides");
gotoXY (TAB, 7);
printz ("Piece+loc: ");
a = white;
do
{
gotoXY (TAB, 6);
printz ("Editing: %s", ColorStr[a]);
gotoXY (TAB + 12, 7);
ClrEoln ();
read_line(s);
if (s[0] == '#')
{
for(sq = 0; sq < 64; sq++)
{
board[sq] = no_piece;
color[sq] = neutral;
DrawPiece (sq);
}
}
if (s[0] == 'c' || s[0] == 'C')
a = otherside[a];
c = s[1] - 'a';
r = s[2] - '1';
if ((c >= 0) && (c < 8) && (r >= 0) && (r < 8))
{
sq = locn (r, c);
for (i = king; i > no_piece; i--)
if ((s[0] == pxx[i]) || (s[0] == qxx[i]))
break;
board[sq] = i;
color[sq] = (board[sq] == no_piece) ? neutral : a;
DrawPiece (sq);
}
} while (s[0] != '.');
for (sq = 0; sq < 64; sq++)
Mvboard[sq] = (board[sq] != Stboard[sq]) ? 10 : 0;
GameCnt = 0;
Game50 = 1;
ZeroRPT ();
Sdepth = 0;
InitializeStats ();
ClrScreen ();
UpdateDisplay (0, 0, 1, 0);
}
void
ShowPlayers (void)
{ int y;
static char gnu[] = "GNU CHESS 3.1 MAR 90";
static char human[] = "Human";
if (flag.reverse)
y = 15;
else
y = 0;
draw_small_string(TAB * FONT_WIDTH, y * FONT_HEIGHT,
computer == black ? gnu : human);
if (flag.reverse)
y = 0;
else
y = 15;
draw_small_string(TAB * FONT_WIDTH, y * FONT_HEIGHT,
computer == white ? gnu : human);
}
void
ShowDepth (char ch)
{
gotoXY (TAB, LINE_DEPTH);
printz ("Depth=%2d%c", Sdepth, ch);
}
void
ShowScore (short score)
{
gotoXY (TAB + 10, LINE_DEPTH);
printz ("Sc=%d", score);
ClrEoln ();
}
void
ShowMessage (char *s)
{
gotoXY (TAB, 12);
printz ("%s", s);
ClrEoln ();
}
void
ClearMessage (void)
{
gotoXY (TAB, LINE_YOUR_GO);
ClrEoln ();
}
void
ShowCurrentMove (short int pnt, short int f, short int t)
{
if (Sdepth < 3)
return;
algbr (f, t, false);
gotoXY (TAB, 4);
printz ("(%2d) %4s", pnt, mvstr[0]);
}
void
ShowSidetomove (void)
{
OutputMove();
/*
gotoXY (TAB, 9);
printz ("%2d: %s", 1 + GameCnt / 2, ColorStr[player]);
ClrEoln ();
*/
}
void
ShowPrompt (void)
{
gotoXY (TAB, LINE_YOUR_GO);
printz ("Your go? ");
ClrEoln ();
}
void
ShowNodeCnt (long int NodeCnt, long int evrate)
{
gotoXY (TAB, 3);
printz ("N=%ld N/Sec=%d", NodeCnt, (int) evrate);
ClrEoln ();
}
void
ShowResults (short int score, short unsigned int *bstline, char ch)
{
unsigned char d, ply;
int col;
if (flag.post == 0)
return;
/***********************************************/
/* Dont update screen for first couple of */
/* levels because score changes too */
/* quickly and uses up more CPU than the */
/* thinking time. */
/***********************************************/
if (Sdepth < 3)
return;
col = 3;
ShowDepth (ch);
ShowScore (score);
d = 4;
for (ply = 1; bstline[ply] > 0; ply++)
{
if (col == 3) {
gotoXY (TAB, ++d);
ClrEoln ();
col = 0;
}
algbr ((short) bstline[ply] >> 8, (short) bstline[ply] & 0xFF, false);
printz ("%5s ", mvstr[0]);
col++;
}
ClrEoln ();
while (d < 8)
{
gotoXY (TAB, ++d);
ClrEoln ();
}
}
void
SearchStartStuff (short int side)
{
short i;
signal (SIGINT, TerminateSearch);
side++; /* shut up the compiler */
for (i = 4; i < 9; i++)
{
gotoXY (TAB, i);
ClrEoln ();
}
}
void
OutputMove (void)
{
register int i, j, f, t;
char *cp;
if (root == NULL || GameCnt < 1)
return;
UpdateDisplay (root->f, root->t, 0, (short) root->flags);
cp = count_pieces(black);
gotoXY(TAB, 1);
printz(cp);
ClrEoln();
cp = count_pieces(white);
gotoXY(TAB, LINE_BOT_PIECES);
printz(cp);
ClrEoln();
i = 0;
if (GameCnt) {
if (GameCnt < 6)
j = 1;
else
j = (GameCnt - 6) | 1;
for (; i < 3 && j <= GameCnt; ) {
gotoXY(TAB, 9 + i++);
f = GameList[j].gmove >> 8;
t = (GameList[j].gmove & 0xFF);
algbr (f, t, false);
printz("%2d: %s ", (j + 1) / 2, mvstr[0]);
if (++j > GameCnt) {
ClrEoln();
break;
}
f = GameList[j].gmove >> 8;
t = (GameList[j++].gmove & 0xFF);
algbr (f, t, false);
printz("%s", mvstr[0]);
}
}
while (i < 3) {
gotoXY(TAB, 9 + i++);
ClrEoln();
}
gotoXY (TAB, 12);
if (root->flags & draw)
printz ("Drawn game!");
else if (root->score == -9999)
printz ("Opponent mates!");
else if (root->score == 9998)
printz ("Computer mates!");
else if (root->score < -9000)
printz ("Opponent mates soon!");
else if (root->score > 9000)
printz ("Computer mates soon!");
ClrEoln ();
ShowNodeCnt (NodeCnt, evrate);
gotoXY (TAB, LINE_MAX_TREE);
for (i = 1999; i >= 0 && Tree[i].f == 0 && Tree[i].t == 0; i--);
printz ("Max Tree=%d", i);
ClrEoln ();
}
void
ElapsedTime (short int iop)
/*
Determine the time that has passed since the search was started. If
the elapsed time exceeds the target (ResponseTime+ExtraTime) then set
timeout to true which will terminate the search.
*/
{
et = time ((long *) 0) - time0;
if (et < 0)
et = 0;
ETnodes += 50;
if (et > et0 || iop == 1)
{
if (et > ResponseTime + ExtraTime && Sdepth > 1)
flag.timeout = true;
et0 = et;
if (iop == 1)
{
time0 = time ((long *) 0);
et0 = 0;
}
if (et > 0)
/* evrate used to be Nodes / cputime I dont` know why */
evrate = NodeCnt / (et + ft);
else
evrate = 0;
ETnodes = NodeCnt + 50;
UpdateClocks ();
}
}
void
UpdateClocks (void)
{
short m, s;
m = (short) (et / 60);
s = (short) (et - 60 * (long) m);
if (TCflag)
{
m = (short) ((TimeControl.clock[player] - et) / 60);
s = (short) (TimeControl.clock[player] - et - 60 * (long) m);
}
if (m < 0)
m = 0;
if (s < 0)
s = 0;
if (player == white)
gotoXY (TAB + 12, (flag.reverse) ? 0 : 15);
else
gotoXY (TAB + 12, (flag.reverse) ? 15 : 0);
printz ("%d:%02d", m, s);
ClrEoln ();
ShowNodeCnt (NodeCnt, evrate);
refresh ();
}
void
SetTimeControl (void)
{
if (TCflag)
{
TimeControl.moves[white] = TimeControl.moves[black] = TCmoves;
TimeControl.clock[white] = TimeControl.clock[black] = 60 * (long) TCminutes;
}
else
{
TimeControl.moves[white] = TimeControl.moves[black] = 0;
TimeControl.clock[white] = TimeControl.clock[black] = 0;
Level = 60 * (long) TCminutes;
}
et = 0;
ElapsedTime (1);
}
void
gotoXY (short int x, short int y)
{
putchar(ESC);
putchar('[');
param(y+1);
putchar(';');
param(x+1);
putchar('H');
ttcol = x;
ttrow = y;
}
void
ClrScreen (void)
{ register int i;
G_Mode(G_GRAPHICS);
for (i = 0; i < MAX_LINES; )
ttwidth[i++] = 0;
}
void
ClrEoln (void)
{ int i;
for (i = ttcol; i < ttwidth[ttrow]; i++)
putchar(' ');
if (i != ttcol)
gotoXY(ttcol, ttrow);
ttwidth[ttrow] = ttcol;
refresh ();
}
void
param(short n)
{
if (n >= 10)
{
register short d, q;
q = n/10; d = n%10;
putchar(q + '0');
putchar(d + '0');
}
else
putchar(n + '0');
}
void
DrawPiece (short int sq)
{ int p = board[sq];
int row = VIR_R(sq);
int col = VIR_C(sq);
int iswhite = !Vblack(sq);
switch (color[sq])
{
case black:
draw_piece(row, col,
iswhite ? b_on_w_piece[p] : b_on_b_piece[p]);
break;
case neutral:
draw_piece(row, col,
iswhite ? w_on_w_piece[0] : b_on_b_piece[0]);
break;
case white:
draw_piece(row, col,
iswhite ? w_on_w_piece[p] : w_on_b_piece[p]);
break;
default:
ShowMessage ("DrawPiece: error");
break;
}
}
void
DrawSquare (short int sq)
{
int iswhite = !Vblack(sq);
int row = VIR_R(sq);
int col = VIR_C(sq);
draw_piece(row, col,
iswhite ? w_on_w_piece[0] : b_on_w_piece[0]);
}
void
DrawCoords (void)
{
register short z;
char buf[10];
buf[1] = '\0';
for (z = 0; z <= 7; z++) {
buf[0] = (7 - z) + '1';
draw_small_string(0, 15 * z + 4, buf);
}
for (z = 0; z <= 7; z++) {
buf[0] = z + 'A';
draw_small_string(15 * z + 10, MAX_Y - 6, buf);
}
}
void
UpdateDisplay (short int f, short int t, short int redraw, short int isspec)
{
short sq;
if (redraw)
{
ShowPlayers ();
for (sq = 0; sq < 64; sq++)
{
DrawSquare (sq);
DrawPiece (sq);
}
if (coords)
DrawCoords ();
}
else
{
DrawPiece (f);
DrawPiece (t);
if (isspec & cstlmask)
if (t > f)
{
DrawPiece (f + 3);
DrawPiece (t - 1);
}
else
{
DrawPiece (f - 4);
DrawPiece (t + 1);
}
else if (isspec & epmask)
{
DrawPiece (t - 8);
DrawPiece (t + 8);
}
}
refresh ();
}
void
GetGame (void)
{
FILE *fd;
char fname[256], tname[256];
char *tmp;
int c;
short sq;
unsigned short m;
tname[0] = 0;
if (tmp = getenv ("HOME")) {
strcpy (fname, tmp);
strcat (fname, "/");
}
else
fname[0] = '\0';
ShowMessage ("File name: ");
read_line(tname);
if (tname[0])
strcat (fname, tname);
else
strcat (fname, "chess.000");
ShowMessage("Loading ");
printz ("%s", fname);
if ((fd = fopen (fname, "r")) == NULL)
{
ShowMessage ("Load failed");
return;
}
fscanf (fd, "%hd%hd%hd", &computer, &opponent, &Game50);
fscanf (fd, "%hd%hd", &castld[white], &castld[black]);
fscanf (fd, "%hd%hd", &TCflag, &OperatorTime);
fscanf (fd, "%ld%ld%hd%hd",
&TimeControl.clock[white], &TimeControl.clock[black],
&TimeControl.moves[white], &TimeControl.moves[black]);
for (sq = 0; sq < 64; sq++)
{
fscanf (fd, "%hd%hd", &m, &Mvboard[sq]);
board[sq] = (m >> 8);
color[sq] = (m & 0xFF);
if (color[sq] == 0)
color[sq] = neutral;
else
--color[sq];
}
GameCnt = 0;
c = '?';
while (c != EOF)
{
++GameCnt;
c = fscanf (fd, "%hd%hd%hd%ld%hd%hd%hd", &GameList[GameCnt].gmove,
&GameList[GameCnt].score, &GameList[GameCnt].depth,
&GameList[GameCnt].nodes, &GameList[GameCnt].time,
&GameList[GameCnt].piece, &GameList[GameCnt].color);
if (GameList[GameCnt].color == 0)
GameList[GameCnt].color = neutral;
else
--GameList[GameCnt].color;
}
GameCnt--;
if (TimeControl.clock[white] > 0)
TCflag = true;
computer--;
opponent--;
fclose (fd);
InitializeStats ();
Sdepth = 0;
ShowMessage ("Done. Press <Ret>");
fflush (stdin);
getchar ();
UpdateDisplay (0, 0, 1, 0);
}
void
SaveGame (void)
{
FILE *fd;
char fname[256], tname[256];
char *tmp;
short sq, i, c;
tname[0] = 0;
if (tmp = getenv ("HOME")) {
strcpy (fname, tmp);
strcat (fname, "/");
}
else
fname[0] = '\0';
ShowMessage ("File name: ");
refresh ();
read_line(tname);
if (tname[0])
strcat (fname, tname);
else
strcat (fname, "chess.000");
ShowMessage("Saving ");
printz ("%s", fname);
if (NULL == (fd = fopen (fname, "w")))
{
ShowMessage ("Not saved");
return;
}
fprintf (fd, "%d %d %d\n", computer + 1, opponent + 1, Game50);
fprintf (fd, "%d %d\n", castld[white], castld[black]);
fprintf (fd, "%d %d\n", TCflag, OperatorTime);
fprintf (fd, "%ld %ld %d %d\n",
TimeControl.clock[white], TimeControl.clock[black],
TimeControl.moves[white], TimeControl.moves[black]);
for (sq = 0; sq < 64; sq++)
{
if (color[sq] == neutral)
c = 0;
else
c = color[sq] + 1;
fprintf (fd, "%d %d\n", 256 * board[sq] + c, Mvboard[sq]);
}
for (i = 1; i <= GameCnt; i++)
{
if (GameList[i].color == neutral)
c = 0;
else
c = GameList[i].color + 1;
fprintf (fd, "%d %d %d %ld %d %d %d\n",
GameList[i].gmove, GameList[i].score, GameList[i].depth,
GameList[i].nodes, GameList[i].time,
GameList[i].piece, c);
}
fclose (fd);
ShowMessage ("Done. Press <Ret>");
fflush (stdin);
getchar ();
}
void
ListGame (void)
{
FILE *fd;
char fname[256];
char *tmp;
short i, f, t;
if (tmp = getenv ("HOME")) {
strcpy (fname, tmp);
strcat(fname, "/");
}
else
fname[0] = '\0';
strcat (fname, "chess.lst");
if (fd = fopen (fname, "w"))
ShowMessage ("Writing chess.lst");
else
{
ShowMessage ("Cannot write chess.lst");
return;
}
fprintf (fd, "\n");
fprintf (fd, " score depth nodes time ");
fprintf (fd, " score depth nodes time\n");
for (i = 1; i <= GameCnt; i++)
{
f = GameList[i].gmove >> 8;
t = (GameList[i].gmove & 0xFF);
algbr (f, t, false);
if (i & 1)
fprintf (fd, "\n");
else
fprintf (fd, " ");
fprintf (fd, "%5s %5d %2d %7ld %5d", mvstr[0],
GameList[i].score, GameList[i].depth,
GameList[i].nodes, GameList[i].time);
}
fprintf (fd, "\n\n");
fclose (fd);
ShowMessage ("chess.lst written");
}
void
Undo (void)
/*
Undo the most recent half-move.
*/
{
short f, t;
f = GameList[GameCnt].gmove >> 8;
t = GameList[GameCnt].gmove & 0xFF;
if (board[t] == king && distance (t, f) > 1)
(void) castle (GameList[GameCnt].color, f, t, 2);
else
{
/* Check for promotion: */
if ((color[t] == white && row (f) == 6 && row (t) == 7)
|| (color[t] == black && row (f) == 1 && row (t) == 0))
{
int g, from = f;
for (g = GameCnt - 1; g > 0; g--)
if (GameList[g].gmove & 0xFF == from)
from = GameList[g].gmove >> 8;
if ((color[t] == white && row (from) == 1)
|| (color[t] == black && row (from) == 6))
board[t] = pawn;
}
board[f] = board[t];
color[f] = color[t];
board[t] = GameList[GameCnt].piece;
color[t] = GameList[GameCnt].color;
if (color[t] != neutral)
Mvboard[t]--;
Mvboard[f]--;
}
if (TCflag)
++TimeControl.moves[color[f]];
GameCnt--;
computer = otherside[computer];
opponent = otherside[opponent];
flag.mate = false;
Sdepth = 0;
UpdateDisplay (0, 0, 1, 0);
InitializeStats ();
OutputMove();
}
void
ChangeAlphaWindow (void)
{
ShowMessage ("Awindow= ");
Awindow = read_number(Awindow);
}
void
ChangeBetaWindow (void)
{
ShowMessage ("Bwindow= ");
Bwindow = read_number(Bwindow);
}
void
GiveHint (void)
{
char s[40];
algbr ((short) (hint >> 8), (short) (hint & 0xFF), false);
strcpy (s, "try ");
strcat (s, mvstr[0]);
ShowMessage (s);
}
void
ChangeSearchDepth (void)
{
ShowMessage ("depth= ");
MaxSearchDepth = read_number(MaxSearchDepth);
}
void
SetContempt (void)
{
ShowMessage ("contempt= ");
contempt = read_number(contempt);
}
void
ChangeXwindow (void)
{
ShowMessage ("xwndw= ");
xwndw = read_number(xwndw);
}
void
SelectLevel (void)
{
static struct {
int moves;
int minutes;
} tbl[] = {
{60, 5},
{60, 15},
{60, 30},
{40, 30},
{40, 60},
{40, 120},
{40, 240},
{1, 15},
{1, 60},
{1, 600}
};
ClrScreen ();
gotoXY (12, 0);
printz ( "GNU CHESS v3.1");
gotoXY (10, 1);
printz ("ported by Paul Fox");
gotoXY (4, 4);
printz (" 1. 60 moves in 5 minutes");
gotoXY (4, 5);
printz (" 2. 60 moves in 15 minutes");
gotoXY (4, 6);
printz (" 3. 60 moves in 30 minutes");
gotoXY (4, 7);
printz (" 4. 40 moves in 30 minutes");
gotoXY (4, 8);
printz (" 5. 40 moves in 60 minutes");
gotoXY (4, 9);
printz (" 6. 40 moves in 120 minutes");
gotoXY (4, 10);
printz (" 7. 40 moves in 240 minutes");
gotoXY (4, 11);
printz (" 8. 1 move in 15 minutes");
gotoXY (4, 12);
printz (" 9. 1 move in 60 minutes");
gotoXY (4, 13);
printz ("10. 1 move in 600 minutes");
OperatorTime = 1;
TCmoves = 60;
TCminutes = 5;
gotoXY (4, 15);
printz ("Enter Level: ");
refresh ();
Level = read_number(Level) - 1;
if (Level >= 0 && Level < sizeof tbl / sizeof tbl[0]) {
TCmoves = tbl[Level].moves;
TCminutes = tbl[Level].minutes;
}
TCflag = (TCmoves > 1);
SetTimeControl ();
ClrScreen ();
UpdateDisplay (0, 0, 1, 0);
}
void
ShowPostnValue (short int sq)
/*
must have called ExaminePosition() first
*/
{ int x, y;
char buf[10];
short score;
x = VIR_C(sq) * 15;
y = VIR_R(sq) * 15;
ScorePosition (color[sq], &score);
if (color[sq] != neutral) {
sprintf (buf, "%3d", svalue[sq]);
draw_small_string(x + 7, y + 1, buf);
}
}
void
ShowPostnValues (void)
{
short sq, score;
ExaminePosition ();
for (sq = 0; sq < 64; sq++)
ShowPostnValue (sq);
ScorePosition (opponent, &score);
ShowScore (score);
}
void
DoDebug (void)
{
short c, p, sq, tp, tc, tsq, score;
char s[40];
ExaminePosition ();
ShowMessage ("Enter piece: ");
read_line(s);
c = neutral;
if (s[0] == 'w' || s[0] == 'W')
c = white;
if (s[0] == 'b' || s[0] == 'B')
c = black;
for(p = king; p > no_piece; p--)
if ((s[1] == pxx[p]) || (s[1] == qxx[p]))
break;
for (sq = 0; sq < 64; sq++)
{
tp = board[sq];
tc = color[sq];
board[sq] = p;
color[sq] = c;
tsq = PieceList[c][1];
PieceList[c][1] = sq;
ShowPostnValue (sq);
PieceList[c][1] = tsq;
board[sq] = tp;
color[sq] = tc;
}
ScorePosition (opponent, &score);
ShowScore (score);
}
void
TestSpeed(void (*f) (short int side, short int ply))
{
short i;
long t1, t2;
t1 = time (0);
for (i = 0; i < 1000; i++)
{
f (opponent, 2);
}
t2 = time (0);
NodeCnt = 1000L * (TrPnt[3] - TrPnt[2]);
evrate = NodeCnt / (t2 - t1);
ShowNodeCnt (NodeCnt, evrate);
}
void
InputCommand (void)
/*
Process the users command. If easy mode is OFF (the computer is thinking
on opponents time) and the program is out of book, then make the 'hint'
move on the board and call SelectMove() to find a response. The user
terminates the search by entering ^C (quit siqnal) before entering a
command. If the opponent does not make the hint move, then set Sdepth to
zero.
*/
{
short ok, tmp;
unsigned short mv;
char s[80];
ok = flag.quit = false;
player = opponent;
ShowSidetomove ();
ft = 0;
if (hint > 0 && !flag.easy && Book == NULL)
{
fflush (stdout);
time0 = time ((long *) 0);
algbr ((short) hint >> 8, (short) hint & 0xFF, false);
strcpy (s, mvstr[0]);
tmp = epsquare;
if (VerifyMove (s, 1, &mv))
{
ShowPrompt ();
SelectMove (computer, 2);
(void) VerifyMove (mvstr[0], 2, &mv);
if (Sdepth > 0)
Sdepth--;
}
ft = time ((long *) 0) - time0;
epsquare = tmp;
}
signal (SIGINT, Die);
#ifndef MSDOS
signal (SIGQUIT, Die);
#endif /* MSDOS */
while (!(ok || flag.quit))
{
ShowPrompt ();
read_line(s);
player = opponent;
ok = VerifyMove (s, 0, &mv);
if (ok)
OutputMove();
if (ok && mv != hint)
{
Sdepth = 0;
ft = 0;
}
if (*s == '\0')
UpdateDisplay (0, 0, 1, 0);
if (strcmp (s, "bd") == 0)
{
ClrScreen ();
UpdateDisplay (0, 0, 1, 0);
ShowSidetomove();
}
if ((strcmp (s, "quit") == 0) || (strcmp (s, "exit") == 0))
flag.quit = true;
if (strcmp (s, "post") == 0)
flag.post = !flag.post;
if (strcmp (s, "edit") == 0)
EditBoard ();
if (strcmp (s, "go") == 0)
ok = true;
if (strcmp (s, "help") == 0)
help ();
if (strcmp (s, "force") == 0)
flag.force = !flag.force;
if (strcmp (s, "book") == 0)
Book = NULL;
if (strcmp (s, "undo") == 0 && GameCnt > 0)
Undo ();
if (strcmp (s, "new") == 0)
NewGame ();
if (strcmp (s, "list") == 0)
ListGame ();
if (strcmp (s, "level") == 0)
SelectLevel ();
if (strcmp (s, "hash") == 0)
flag.hash = !flag.hash;
if (strcmp (s, "beep") == 0)
flag.beep = !flag.beep;
if (strcmp (s, "Awindow") == 0)
ChangeAlphaWindow ();
if (strcmp (s, "Bwindow") == 0)
ChangeBetaWindow ();
if (strcmp (s, "hint") == 0)
GiveHint ();
if (strcmp (s, "both") == 0)
{
flag.bothsides = !flag.bothsides;
Sdepth = 0;
SelectMove (opponent, 1);
ok = true;
}
if (strcmp (s, "reverse") == 0)
{
flag.reverse = !flag.reverse;
ClrScreen ();
UpdateDisplay (0, 0, 1, 0);
}
if (strcmp (s, "switch") == 0)
{
computer = otherside[computer];
opponent = otherside[opponent];
flag.force = false;
Sdepth = 0;
ok = true;
}
if (strcmp (s, "white") == 0)
{
computer = white;
opponent = black;
ok = true;
flag.force = false;
Sdepth = 0;
}
if (strcmp (s, "black") == 0)
{
computer = black;
opponent = white;
ok = true;
flag.force = false;
Sdepth = 0;
}
if (strcmp (s, "remove") == 0 && GameCnt > 1)
{
Undo ();
Undo ();
}
if (strcmp (s, "get") == 0)
GetGame ();
if (strcmp (s, "save") == 0)
SaveGame ();
if (strcmp (s, "depth") == 0)
ChangeSearchDepth ();
if (strcmp (s, "random") == 0)
dither = 6;
if (strcmp (s, "easy") == 0)
flag.easy = !flag.easy;
if (strcmp (s, "contempt") == 0)
SetContempt ();
if (strcmp (s, "xwndw") == 0)
ChangeXwindow ();
if (strcmp (s, "coords") == 0)
{
coords = !coords;
UpdateDisplay (0, 0, 1, 0);
}
if (strcmp (s, "test") == 0)
{
ShowMessage("MoveList speed test");
TestSpeed (MoveList);
ShowMessage("CaptureList speed");
TestSpeed (CaptureList);
}
if (strcmp (s, "p") == 0)
ShowPostnValues ();
if (strcmp (s, "debug") == 0)
DoDebug ();
}
ClearMessage ();
ElapsedTime (1);
if (flag.force)
{
computer = opponent;
opponent = otherside[computer];
}
signal (SIGINT, TerminateSearch);
}
void
draw_bitmap(x, y, p)
int x, y;
char *p;
{
G_ImagePut(x, y, p, G_FORCE);
}
void
draw_piece(r, c, p)
int r, c;
struct bitmap *p;
{
draw_bitmap(c * 15 + 5, (7 - r) * 15, p);
}
# define ARGS a, b, c, d, e, f, g, h
printz(ARGS)
long ARGS;
{ char buf[80];
sprintf(buf, ARGS);
printf("%s", buf);
ttcol += strlen(buf);
if (ttcol > ttwidth[ttrow])
ttwidth[ttrow] = ttcol;
}